package io.jsen.meta.diff;

import com.google.common.reflect.TypeToken;
import io.jsen.meta.diff.feature.annotation.MetaFieldFeature;
import io.jsen.meta.diff.obj.Convert;
import io.jsen.meta.diff.obj.MetaObject;

/**
 * 配置主要有两类
 * 1，MetaConvert注解相关功能：转化器，见registerConvert方法
 * 2，MetaFieldAnnotation注解相关功能：定义字段是不是索引、需不需要忽略diff、字段的别名，字段控制器（定义删除字段和自定义索引构建）
 *
 * @author jsen
 * @date 2021/09/18
 **/
public interface IMetaContext {


    /**
     * 加载指定的field配置文件
     *
     * @param path 文件位置
     */
    void loadDefine(String path);

    /**
     * 加载指定的field配置文件
     *
     * @param typeToken 类的token
     * @param <T>       native类型
     */
    <T> void loadDefine(TypeToken<T> typeToken);

    /**
     * diff两个native对象
     *
     * @param newObj newNative
     * @param oldObj oldNative
     * @param <T>    native type
     * @return t
     */
    <T> MetaObject<?, ?> diffMeta(TypeToken<T> typeToken, T newObj, T oldObj);

    /**
     * 把一个native对象转为meta对象
     *
     * @param nativeObj native
     * @param <T>       native type
     * @return t
     */
    <T> MetaObject<?, ?> toMeta(TypeToken<T> typeToken, T nativeObj);

    /**
     * metaObject转为native对象
     *
     * @param metaObject metaObject
     * @param <T>        native type
     * @return t
     */
    <T> T toNative(MetaObject<?, ?> metaObject);

    /**
     * 注册字段转换器
     * <p>
     * 字段转换器有三个地方可以注入
     * 1，直接调用这个方法注入
     * 2，在字段上加上 {@link MetaFieldFeature#fieldControl()} 注解，传入一个转换器
     * 3，根据配置文件解析（TODO）
     *
     * @param clazz   nativeClass / metaObjectClass
     * @param convert convert
     * @param <S>     in type
     * @param <T>     out type
     */
    <S, T> void registerConvert(Class<?> clazz, Convert<S, T> convert);
}
